#include <iostream>
#include <vector>
#include "Thread.hpp"
#include "BlockQueue.hpp"
#include <string>
using std::cout;
using std::endl;
using namespace ThreadModule;

using blockqueue_t = BlockQueue<Task>;

// int a = 10;
// blockqueue_t *bq = new blockqueue_t(10);

class ThreadData
{
public:
    ThreadData(blockqueue_t *&bq, std::string name)
        : _bq(bq), _name(name)
    {
    }
    std::string Name() { return _name; }
    // private:
    blockqueue_t *&_bq;
    std::string _name;
};

void PrintHello()
{
    cout << "hello world" << endl;
}

void Consumer(ThreadData *&bq)
{
    // int cnt = 0;
    while (true)
    {
        // bq->Pop(&cnt);
        // cout << "Consumer consum data is :" << cnt << endl;
        // cout << "Consumer: " << bq << endl;
        // sleep(1);
        Task t;
        bq->_bq->Pop(&t);
        t();//属于消费者私有
        printf("Consumer consume data is : %s ", bq->_name.c_str());
        // cout << "Consumer consume data is :" << <<bq->_name.c_str() << endl;
        // printf("Consumer consume data is : %s , consum %s",bq->_name.c_str(),t());
        // sleep(1);
    }
}

void Productor(ThreadData *&bq)
{
    // int cnt = 10;
    while (true)
    {
        sleep(3);
        Task t = PrintHello;
        bq->_bq->Enqueue(t);
        printf("Productor product data is : %s ", bq->_name.c_str());
        // cout << "Productor product data is :" << bq->_name.c_str() << endl;
        // bq->Enqueue(cnt);
        // cout << "Productor product data is :" << cnt << endl;
        // cnt++;
    }
}

void StartCom(std::vector<Thread<ThreadData *>> *&threads, int num, blockqueue_t *&bq, func_t<ThreadData *> func,std::vector<ThreadData *>* dtd)
{
    for (int i = 0; i < num; i++)
    {
        std::string name = "thread -" + std::to_string(1 + i);
        ThreadData *td = new ThreadData(bq, name);
        threads->emplace_back(func, td, name);
        threads->back().Start();
        dtd->push_back(td);
    }
}

void StartConsumer(std::vector<Thread<ThreadData *>> *&threads, int num, blockqueue_t *&bq,std::vector<ThreadData *>* dtd)
{
    StartCom(threads, num, bq, Consumer,dtd);
}

void StartProductor(std::vector<Thread<ThreadData *>> *&threads, int num, blockqueue_t *&bq,std::vector<ThreadData *>* dtd)
{
    StartCom(threads, num, bq, Productor,dtd);
}

void WaitAllThread(std::vector<Thread<ThreadData *>> &threads)
{
    for (auto &thread : threads)
    {
        thread.Join();
    }
}

int main()
{
    blockqueue_t *bq = new blockqueue_t(10); // 全局定义一个配合ThreadData

    std::vector<Thread<ThreadData *>> threads;
    std::vector<Thread<ThreadData *>> *pthreads = &threads;
    std::vector<ThreadData *> dtds;
    StartConsumer(pthreads, 5, bq,&dtds);
    StartProductor(pthreads, 1, bq,&dtds);
    WaitAllThread(threads);
    delete bq;
    for(auto dtd:dtds )
    {
        delete dtd;
    }
    return 0;
}